/**
 * API 请求方法封装
 *
 * @author Claude
 */

import type {AxiosError, AxiosInstance, AxiosResponse, InternalAxiosRequestConfig} from 'axios'
import type {ApiResponse, ApiResult, RequestConfig} from '@/types/api'
import {ResponseHandler} from '@/utils/responseHandler'

/**
 * 基础请求方法
 */
export class BaseApiClient {
    private config: RequestConfig = {}

    constructor(private client: AxiosInstance) {
    }

    /**
     * GET 请求
     */
    async get<T = any>(
        url: string,
        config?: RequestConfig
    ): Promise<ApiResult<T>> {
        try {
            const response = await this.client.get<T>(url, {
                ...config,
                ...this.addConfig(config)
            })
            return this.handleResponse(response)
        } catch (error) {
            return this.handleError(error as AxiosError<ApiResponse>)
        }
    }

    /**
     * POST 请求
     */
    async post<T = any>(
        url: string,
        data?: any,
        config?: RequestConfig
    ): Promise<ApiResult<T>> {
        try {
            const response = await this.client.post<T>(url, data, {
                ...config,
                ...this.addConfig(config)
            })
            return this.handleResponse(response)
        } catch (error) {
            return this.handleError(error as AxiosError<ApiResponse>)
        }
    }

    /**
     * PUT 请求
     */
    async put<T = any>(
        url: string,
        data?: any,
        config?: RequestConfig
    ): Promise<ApiResult<T>> {
        try {
            const response = await this.client.put<T>(url, data, {
                ...config,
                ...this.addConfig(config)
            })
            return this.handleResponse(response)
        } catch (error) {
            return this.handleError(error as AxiosError<ApiResponse>)
        }
    }

    /**
     * PATCH 请求
     */
    async patch<T = any>(
        url: string,
        data?: any,
        config?: RequestConfig
    ): Promise<ApiResult<T>> {
        try {
            const response = await this.client.patch<T>(url, data, {
                ...config,
                ...this.addConfig(config)
            })
            return this.handleResponse(response)
        } catch (error) {
            return this.handleError(error as AxiosError<ApiResponse>)
        }
    }

    /**
     * DELETE 请求
     */
    async delete<T = any>(
        url: string,
        config?: RequestConfig
    ): Promise<ApiResult<T>> {
        try {
            const response = await this.client.delete<T>(url, {
                ...config,
                ...this.addConfig(config)
            })
            return this.handleResponse(response)
        } catch (error) {
            return this.handleError(error as AxiosError<ApiResponse>)
        }
    }

    /**
     * 上传文件
     */
    async upload<T = any>(
        url: string,
        formData: FormData,
        config?: RequestConfig
    ): Promise<ApiResult<T>> {
        try {
            const response = await this.client.post<T>(url, formData, {
                ...config,
                headers: {
                    'Content-Type': 'multipart/form-data',
                    ...config?.headers
                }
            })
            return this.handleResponse(response)
        } catch (error) {
            return this.handleError(error as AxiosError<ApiResponse>)
        }
    }

    /**
     * 下载文件
     */
    async download(
        url: string,
        filename?: string,
        config?: RequestConfig
    ): Promise<void> {
        try {
            const response = await this.client.get(url, {
                ...config,
                responseType: 'blob'
            })

            // 创建下载链接
            const blob = new Blob([response.data])
            const downloadUrl = window.URL.createObjectURL(blob)
            const link = document.createElement('a')
            link.href = downloadUrl
            link.download = filename || 'download'
            document.body.appendChild(link)
            link.click()
            document.body.removeChild(link)
            window.URL.revokeObjectURL(downloadUrl)
        } catch (error) {
            console.error('Download failed:', error)
            throw error
        }
    }

    /**
     * 处理成功响应
     */
    private handleResponse<T>(response: AxiosResponse<T>): ApiResult<T> {
        return ResponseHandler.handleSuccess(response as AxiosResponse<ApiResponse<T>>, this.config)
    }

    /**
     * 处理错误响应
     */
    private handleError<T>(error: AxiosError<ApiResponse>): ApiResult<T> {
        return ResponseHandler.handleError(error, this.config)
    }
    /**
     * 添加通用配置
     */
    private addConfig(config?: RequestConfig): InternalAxiosRequestConfig {
        // 存储配置用于响应处理
        this.config = config || {}

        // 创建基础配置，排除headers避免类型冲突
        const {headers, ...configWithoutHeaders} = config || {}

        const finalConfig: InternalAxiosRequestConfig = {
            ...configWithoutHeaders,
            metadata: {
                ...config?.metadata,
                startTime: Date.now()
            },
            headers: {} as any // 确保headers属性存在
        }

        // 单独处理headers
        if (headers) {
            finalConfig.headers = {...headers, 'X-Request-ID': this.generateRequestId()} as any
        } else {
            // 添加请求追踪ID
            ;(finalConfig.headers as any)['X-Request-ID'] = this.generateRequestId()
        }

        return finalConfig
    }

    /**
     * 生成请求ID
     */
    private generateRequestId(): string {
        return Date.now().toString(36) + Math.random().toString(36).substr(2)
    }
}

// 扩展类型声明
declare module 'axios' {
    interface AxiosRequestConfig {
        metadata?: {
            startTime?: number
            [key: string]: any
        }
    }
}